Матч 237, Путь по зеркалам (MirrorPath)

Дивизион 2, Уровень 3

 

Имеется карта лабиринта, в котором находятся зеркала. Стены обозначаются символом ‘#’, пустые места точкой ‘.’. Зеркала наклонены к линии основания под углом 45 градусов и обозначаются символом ‘/’ или ‘`’ (обратный слеш является специальным символом, поэтому здесь не используется). Лабиринт имеет всего два входа на периметре. Лазерный луч пускается в один из входов и выходит в другом. Зеркала расположены так, что пущенный луч в одном из входов всегда достигнет выхода.

Необходимо отобразить на карте ход лазерного луча, используя символы ‘-‘ (горизонтальное движение), ‘|’ (вертикальное движение), ‘+’ (лазер пересекает свой собственный путь).

 

Класс: MirrorPath

Метод: vector<string> path(vector<string> map)

Ограничения: Массив map содержит от 3 до 50 элементов ‘#’, ‘/’, ‘.’, ‘`’, элементы map имеют одинаковую длину от 3 до 50, в точности два символа на границе карты будут ‘.’, углы карты содержат ‘#’.

 

Вход. Карта map, описывающая состояние лабиринта.

 

Выход. Карта с отображением хода лазерного луча.

 

Пример входа

map

{"#.#",

 "#.#",

 "#.#"}

{"############",

 "#######/....",

 "######//####",

 "#####//#####",

 "####//######",

 "..../#######",

 "############"}

{"########.##",

 "#./......`#",

 "#../.`....#",

 "#.`...../.#",

 "#....`.../#",

 "###.#######"}

 

Пример выхода

{"#|#",

 "#|#",

 "#|#"}

{"############",

 "#######/....",

 "######//####",

 "#####//#####",

 "####//######",

 "..../#######",

 "############"}

{"########|##",

 "#./-----+`#",

 "#.|/-`..||#",

 "#.`+-+--/|#",

 "#..|.`---/#",

 "###|#######"}

 

РЕШЕНИЕ

моделирование

 

Проходим по границе лабиринта, ищем один из входов (не имеет значения какой). В координатах (x, y) храним текущее положение лазерного луча. В переменных dx и dy храним направление движения. Ось абсцисс направим вертикально, ординат – горизонтально. Таким образом, map[x][y] обозначает точку в x - ой строке и y - ом столбце. Если, например, найден вход на правой стенке карты, то устанавливаем dx = 0, dy = -1, так как от нее движение будет совершаться влево. Далее будем моделировать ход луча, то есть вместе с ним будем переходить от текущей клетки к следующей, добавляя к x и y соответственно dx и dy.

Пока луч не выйдет за границы карты (что возможно лишь тогда когда луч дойдет до выхода), смотрим на значение map[x][y]:

1. Если map[x][y] = ‘.’, то устанавливаем map[x][y] = ‘|’ или map[x][y] = ‘-’ в зависимости от того, идем мы по вертикальной или горизонтальной прямой. Движение происходит по горизонтали, если dx = 0.

2. Если map[x][y] = ‘/’ или map[x][y] = ‘`’, то следует повернуть на 90 градусов в соответствующем направлении. Для этого меняем значения переменных dx и dy между собой. В первом случае еще следует обратить значения этих переменных на противоположные.

3. Если map[x][y] равно другому какому-нибудь символу (‘-‘ или ‘|’), то ставим на этом месте ‘+’. Луч в этом случае пересекает сам себя.

 

ПРОГРАММА

 

#include <cstdio>

#include <vector>

#include <string>

using namespace std;

 

class MirrorPath

{

public:

  vector<string> path(vector<string> map)

  {

    int i, x, y, dx, dy, n = map.size(), m = map[0].size();

    for(x = y = dx = dy = i = 0; i < n; i++)

    {

      if (map[i][0] == '.') x = i, y = 0, dx = 0, dy = 1;

      if (map[i][m-1] == '.') x = i, y = m - 1, dx = 0, dy = -1;

    }

    for(i = 0; i < m; i++)

    {

      if (map[0][i] == '.') x = 0, y = i, dx = 1, dy = 0;

      if (map[n-1][i] == '.') x = n - 1, y = i, dx = -1, dy = 0;

    }

 

    while((x >= 0) && (x < n) && (y >= 0) && (y < m))

    {

      if (map[x][y] == '.')

      {

        if (dx) map[x][y] = '|'; else map[x][y] = '-';

      } else

      if (map[x][y] == '/')

      {

        swap(dx,dy);

        dx = -dx; dy = -dy;

      } else

      if (map[x][y] == '`') swap(dx,dy);

      else map[x][y] = '+';

        x += dx; y += dy;

    }

    return map;

  }

};